import './fields/charField.js';
import './fields/integerField.js';
import './fields/floatField.js';
import './fields/selectionField.js';
import './fields/booleanField.js';
import './fields/dateField.js';
import './fields/datetimeField.js';
import './fields/textField.js';
import './fields/radio.js';
import './fields/timePicker.js';
import './fields/timeRange.js';
import './fields/dateRange.js';
import './fields/dateTimeRange.js';
import './fields/priority.js';

cqjs.component('dynamicForm', {
    props: ['meta', 'arch', 'data'],
    render() {
        const me = this;
        const arch = cqjs.utils.parseXML(me.$props.arch);
        const form = arch.find('form');
        const toManyArchs = {};
        if (form.length > 0) {
            const tbar = form.children('toolbar');
            me.tbarArch = tbar.prop('outerHTML');
            tbar.remove();
            me.isTree = eval(form.attr('tree'));
            me.cols = eval(form.attr('cols') || me.cols);
            if (me.isTree) {
                me.cols -= 1;
            }
            if (me.cols < 1) {
                me.cols = 1;
            }
            form.css({ 'display': 'grid', 'grid-template-columns': `repeat(${me.cols}, 1fr)` });
            me.initFields(form, toManyArchs);
            me.initTabs(form);
            me.initGroup(form);
            form.attr(':model', "$props.data.data")
                .attr('ref', 'form')
                .attr('label-position', 'top');
        }
        let tpl = arch.children().prop('outerHTML');
        tpl = tpl.replaceAll('<form', '<el-form').replaceAll('/form>', '/el-form>');
        return Vue.compile(tpl).render.call(this);
    },
    methods: {
        resetFields() {
            this.$refs.form.resetFields();
        },
        encode: function (s) {
            return s ? s.replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('"', '%22') : s;
        },
        decode: function (s) {
            return s ? s.replaceAll('&lt;', '<').replaceAll('&gt;', '>').replaceAll('%22', '"') : s;
        },
        convertToKebabCase(str) {
            return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
        },
        initFields(form, toManyArchs) {
            const me = this;
            me.fields = [];
            form.find('field').each(function () {
                const el = $(this);
                if (el.parents('field').length > 0) {
                    return;
                }
                const name = el.attr('name');
                const field = me.$props.meta.fields[name];
                if (!field) {
                    throw new Error('模型' + me.$props.meta.model + '找不到字段' + name);
                }
                if (field.deny) {
                    el.remove();
                } else {
                    const nolabel = el.attr('nolabel');
                    const defVal = el.attr('default') || el.attr('defaultValue');
                    const colspan = Math.min(el.attr('colspan') || 1, me.cols);
                    const rowspan = el.attr('rowspan') || 1;
                    let label = el.attr('label');
                    let help = el.attr('help');
                    let css = 'form-group col-12';
                    let style = `grid-column:span ${colspan};grid-row:span ${rowspan};`;
                    let attrs = '';
                    let html = '<el-form-item prop="' + name + '" ';
                    field.name = field.name || name;
                    field.$defaultValue = defVal || field.defaultValue;
                    $.each(this.attributes, function (i, attr) {
                        if (attr.name === 'class') {
                            css += ' ' + attr.value;
                        } else if (attr.name === 'style') {
                            style += ' ' + attr.value;
                        } else {
                            const v = me.encode(attr.value);
                            if (['name', 'editor'].indexOf(attr.name) == -1) {
                                html += attr.name + '="' + v + '" ';
                            }
                            if (['t-readonly', 't-visible', 'style', 't-reset'].indexOf(attr.name) == -1) {
                                attrs += attr.name + '="' + v + '" ';
                            }
                        }
                    });
                    me.fields.push(name);
                    if (field.type === 'many2many' || field.type === 'one2many') {
                        toManyArchs[name] = el.html();
                    }
                    if (el.attr('readonly') == undefined && field.readonly) {
                        html += 'readonly="1" ';
                    }
                    if (help == undefined) {
                        help = field.help;
                    }
                    html += ` style="${style}" class="${css}"`;
                    if (!label) {
                        label = field.label || field.name;
                    }
                    label = label.t();
                    if (!eval(nolabel)) {
                        html += ` label='${label}'>`;
                    }
                    let editor = el.attr('editor') || (field.type + 'Field');
                    if (!cqjs._components[editor]) {
                        editor = 'charField';
                    }
                    editor = me.convertToKebabCase(editor);
                    html += `<${editor} :data='data' :field='meta.fields["${name}"]' ${attrs}/>`;
                    html += '</el-form-item>';
                    el.replaceWith(html);
                }
            });
        },
        initTabs(form) {
            const me = this;
            form.find('tabs').each(function () {
                const tabs = $(this);
                tabs.remove();
            });
        },
        initGroup(form) {
            const me = this;
            form.find('group').each(function () {
                const group = $(this);
                let css = '';
                let attrs = '';
                const colspan = eval(eval(group.attr('colspan') || me.cols));
                const cols = eval(eval(group.attr('cols') || colspan));
                let styles = 'grid-column:span ' + colspan + ';';
                $.each(this.attributes, function (i, attr) {
                    if (attr.name === 'class') {
                        css += ' ' + attr.value;
                    } else if (attr.name === 'style') {
                        styles += ' ' + attr.value;
                    } else {
                        const v = me.encode(attr.value);
                        attrs += attr.name + '="' + v + '" ';
                    }
                });
                let label = group.attr('label');
                if (label) {
                    label = label.t();
                }
                if(eval(group.attr('collapsable'))){
                    const html = `<el-collapse value="1" class="${css}" style="${styles}" ${attrs}>
                                    <el-collapse-item title="${label}" name="1">
                                        <div style="display:grid;grid-template-columns:repeat(${cols}, 1fr)">
                                            ${group.prop('innerHTML')}
                                        </div>
                                    </el-collapse-item>
                                </el-collapse>`;
                    group.replaceWith(html);

                }else{
                    const html = `<div class="el-collapse${css}" style="${styles}" ${attrs}>
                                    <div class="el-collapse-item__header">${label}</div>
                                    <div style="display:grid;grid-template-columns:repeat(${cols}, 1fr)">
                                        ${group.prop('innerHTML')}
                                    </div>
                                </div>`;
                    group.replaceWith(html);

                }
                //group.remove();
            });
        }
    }
});